package cn.kgc.boot.util;

import cn.hutool.core.io.IORuntimeException;
import cn.hutool.poi.excel.ExcelWriter;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 功能: poi导出excel工具类
 *
 */
public class PoiExcelUtil {

  /**
   * 合并单元格处理,获取合并行
   *
   * @param sheet
   * @return List<CellRangeAddress>
   */
  public static List<CellRangeAddress> getCombineCell(Sheet sheet) {
    List<CellRangeAddress> list = new ArrayList<>();
    // 获得一个 sheet 中合并单元格的数量
    int sheetmergerCount = sheet.getNumMergedRegions();
    // 遍历所有的合并单元格
    for (int i = 0; i < sheetmergerCount; i++) {
      // 获得合并单元格保存进list中
      CellRangeAddress ca = sheet.getMergedRegion(i);
      list.add(ca);
    }
    return list;
  }

  public static int getRowNum(List<CellRangeAddress> listCombineCell, Cell cell, Sheet sheet) {
    int xr = 0;
    int firstC = 0;
    int lastC = 0;
    int firstR = 0;
    int lastR = 0;
    for (CellRangeAddress ca : listCombineCell) {
      // 获得合并单元格的起始行, 结束行, 起始列, 结束列
      firstC = ca.getFirstColumn();
      lastC = ca.getLastColumn();
      firstR = ca.getFirstRow();
      lastR = ca.getLastRow();
      if (cell.getRowIndex() >= firstR && cell.getRowIndex() <= lastR) {
        if (cell.getColumnIndex() >= firstC && cell.getColumnIndex() <= lastC) {
          xr = lastR;
        }
      }
    }
    return xr;
  }

  /**
   * 判断指定的单元格是否是合并单元格
   *
   * @param sheet
   * @param row 行下标
   * @param column 列下标
   * @return
   */
  public static boolean isMergedRegion(Sheet sheet, int row, int column) {
    int sheetMergeCount = sheet.getNumMergedRegions();
    for (int i = 0; i < sheetMergeCount; i++) {
      CellRangeAddress range = sheet.getMergedRegion(i);
      int firstColumn = range.getFirstColumn();
      int lastColumn = range.getLastColumn();
      int firstRow = range.getFirstRow();
      int lastRow = range.getLastRow();
      if (row >= firstRow && row <= lastRow) {
        if (column >= firstColumn && column <= lastColumn) {
          return true;
        }
      }
    }
    return false;
  }

  /** 如果需要合并的话，就合并 */
  public static void mergeIfNeed(
      ExcelWriter writer,
      int firstRow,
      int lastRow,
      int firstColumn,
      int lastColumn,
      Object content) {
    if (lastRow - firstRow > 0 || lastColumn - firstColumn > 0) {
      writer.merge(firstRow, lastRow, firstColumn, lastColumn, content, false);
    } else {
      writer.writeCellValue(firstColumn, firstRow, content);
    }
  }

  public static void writeExcel(HttpServletResponse response, ExcelWriter writer) {
    // response为HttpServletResponse对象
    response.setContentType("application/vnd.ms-excel;charset=utf-8");
    // test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
    response.setHeader("Content-Disposition", "attachment;filename=1.xls");

    ServletOutputStream servletOutputStream = null;
    try {
      servletOutputStream = response.getOutputStream();
      writer.flush(servletOutputStream);
      servletOutputStream.flush();
    } catch (IORuntimeException | IOException e) {
      e.printStackTrace();
    } finally {
      writer.close();
      try {
        if (servletOutputStream != null) {
          servletOutputStream.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  public static void writeExcel(String filename, ExcelWriter writer, HttpServletResponse response) {
    OutputStream ouputStream = null;
    try {
      filename = new String(filename.getBytes("UTF-8"), "ISO-8859-1");
      response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
      response.setHeader("Content-disposition", "attachment;filename=" + filename);
      ouputStream = response.getOutputStream();
      Runtime.getRuntime().gc();
      writer.flush(ouputStream);
      ouputStream.flush();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (null != ouputStream) {
        try {
          ouputStream.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
}
